home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
cmln1086.arc
/
ASSEMBLY.LTG
next >
Wrap
Text File
|
1986-09-15
|
11KB
|
320 lines
Assembly and High-Level Control Constructs by David Long
Listing 1
.xlist ;Listing off
;------------------------------------------
;Structured assembly language macro package
;
;For Microsoft/IBM macro assemblers
;
;Author: David Long
;Last edited: 07/08/86
;------------------------------------------
;
;-------------------
;Miscellaneous notes
;
;Only short jumps are generated for all constructs. Separate stacks
;are used for each construct to facility adding constructs for abnormal
;termination (e.g., BREAK to exit a DO/WHILE/ENDWH loop). Some notes
;on the assembler syntax: The & operator causes the macro parameter(s)
;immediately preceding/following it to be expanded (e.g., if FOO and BAR
;are parameters with values BAR and FOO respectively, FOO&BAR will expand
;as BARFOO). The % operator causes evaluation of an expression (e.g.,
;if the label FOOBAR has the value 31, then calling a macro with the
;parameter %FOOBAR is the same as calling the macro with the parameter
;31 as a string, i.e., as the digits 3 and 1).
;-------------------
;
;-------------------
;Repeat/until macros
;Usage:
;_repeat ;Beginning of loop
; xxxxx ;Body and test
;_until cc ;Loop unless condition code cc holds
;-------------------
;
;_repeat generates the code for the start of a repeat statement.
;
_repeat macro
_push _rep,%_repcnt ;;Save count on stack
_label _rep,%_repcnt ;;Generate label for top of loop
_repcnt = _repcnt+01h
endm
;
;_until generates the code for the end of a repeat statement.
;
_until macro condition
_pop _rep ;;Get count for last _rep in _num
_mkijm condition,_rep,%_num ;;Create jump with inverse condition code
endm
;
;---------------
;Do/while macros
;Usage:
;_do ;Beginning of testè; xxxxx ;Loop test
;_while cc ;Exit if condition code cc does not hold
; xxxxx ;Body
;_endwh ;End of body - loop to start of test
;---------------
;
;_do generates the code for the beginning of a while statement.
;
_do macro
_push _while,%_whilecnt ;;Save count on stack
_label _while,%_whilecnt ;;Generate label for start of test
_whilecnt = _whilecnt+01h
endm
;
;_while generates the code for the middle part of a while statement.
;
_while macro condition
_pop _while ;;Get count for last _do in _num
_push _while,%_num ;;Resave
_mkijm condition,_endwh,%_num ;;Create jump with inverse condition code
endm
;
;_endwh generates the code for the end of a while statement.
;
_endwh macro
_pop _while ;;Get count for last _do in _num
_mkijm un,_while,%_num ;;Create unconditional jump to test
_label _endwh,%_num ;;Generate label for end of construct
endm
;
;-------------------
;If/else macros
;Usage:
;_if cc ;Skip body if condition code cc does not hold
; xxxxx ;Body
;_endif ;End of body
;or:
;_if cc ;Skip to body of _else part if cc does not hold
; xxxxx ;Body of _if part
;_else ;Skip to end of construct and mark start of _else part
; xxxxx ;Body of _else part
;_endif ;End of construct
;-------------------
;
;_if generates the code for the beginning of an if statement.
;
_if macro condition
_push _else,%_elsecnt ;;Save count on stack
_mkijm condition,_else,%_elsecnt ;;Create jump with inverse condition
_elsecnt = _elsecnt+01h
endm
;
;_else generates the code for the middle of an if statement.
;
_else macroè_pop _else ;;Get count for last _if in _num
_push _else,%_num ;;Resave
_mkijm un,_endif,%_num ;;Create unconditional jump to end
_label _else,%_num ;;Mark start of _else part
endm
;
;_endif generates the code for the end of an if statement.
;
_endif macro
_pop _else ;;Get count for last _if/_else
if1 ;;If pass 1
_?def _else,%_num ;; See if _elsexx is defined
if _defined ;; If so
_label _endif,%_num ;; Label end of construct
else ;; If not
_label _else,%_num ;; Pretend the _else is here
endif
endif
endm
;
;---------------------------------------------
;Utility macros for pushing numbers on a stack
;Usage:
;_push stacknm,num ;Push num on stack named stacknm
;---------------------------------------------
;
;_push and _put push a number on the appropriate stack.
;
_push macro stacknm,num
;;Concatenate stacknm with '_ptr' to get the variable which has the top of
;;stack index (call the index n). Call _put with the ASCII representation
;;of n together with stacknm and num.
_put stacknm,%&stacknm&_ptr,num
stacknm&_ptr = stacknm&_ptr+01h ;;Increment stack pointer
endm
;
_put macro stacknm,pntr,num
;;Concatenate stacknm with '_st' and the ASCII representation of the
;;stack pointer to get a variable. Assign num to that variable.
stacknm&_st&pntr = num
endm
;
;----------------------------------------------
;Utility macros for popping numbers off a stack
;Usage:
;_pop stacknm ;Pop the stack named stacknm into the variable _num
;----------------------------------------------
;
;_pop and _fetch get a number off the appropriate stack.
;
_pop macro stacknm
ife stacknm&_ptr ;;If stack is empty
%out Structured statement nesting error
else ;;If stack is not empty
stacknm&_ptr = stacknm&_ptr-01h ;; Decrement stack pointerè ;;Concatenate stacknm with '_ptr' to get the variable which holds the
;;top of stack index (call the index n). Call _fetch with the ASCII
;;representation of n, together with stacknm.
_fetch stacknm,%&stacknm&_ptr
endif
endm
;
_fetch macro stacknm,pntr
;;Concatenate stacknm with '_st' and the ASCII represenation of the stack
;;pointer to get a variable. Set _num to the value of that variable.
_num = stacknm&_st&pntr
endm
;
;------------------------------------------------------------------
;Utility macros for creating jumps with the opposite of a condition
;Usage:
;_mkijm condition,base,number ;Create jump with inverse of condition
;to the label formed by concatenating
;base with number
;------------------------------------------------------------------
;
;_mkijm and _mkjmp create a jump instruction with the inverse of a condition.
;
_mkijm macro condition,base,number
_mkjmp %_inv_&condition,base&number ;;Call _mkjmp with opcode and dest
endm
;
_mkjmp macro jmpopcode,dest
jmp short dest ;;Create jump (compute displacement)
org $-02h ;;Back up to jmp opcode
db jmpopcode ;;Install correct opcode
org $+01 ;;Position back to end of jump
endm
;
;----------------------------
;Miscellaneous utility macros
;Usage:
;_label base,number ;Concatenate base and number to form label
;_?def base,number ;Form label from base and number. Set
; ;_defined to zero if the label is undefined
; ;or set _defined nonzero if it is defined.
;----------------------------
;
;_label forms a label.
;
_label macro base,number
base&number label near
endm
;
;_?def checks to see if a label is defined.
;
_?def macro base,number
ifdef base&number
_defined = 0ffh
elseè _defined = 00h
endif
endm
;
;---------
;Variables
;---------
;
_inv_a = 076h ;Jump opcodes - jna = 076h
_inv_ae = 072h ;jnae = 072h
_inv_b = 073h ;jnb = 073h
_inv_be = 077h ;jnbe = 077h
_inv_c = 073h ;jnc = 073h
_inv_e = 075h ;jne = 075h
_inv_g = 07eh ;jng = 07eh
_inv_ge = 07ch ; ...
_inv_l = 07dh
_inv_le = 07fh
_inv_na = 077h
_inv_nae = 073h
_inv_nb = 072h
_inv_nbe = 076h
_inv_nc = 072h
_inv_ne = 074h
_inv_ng = 07fh
_inv_nge = 07dh
_inv_nl = 07ch
_inv_nle = 07eh
_inv_no = 070h
_inv_np = 07ah
_inv_ns = 078h
_inv_nz = 074h
_inv_o = 071h
_inv_p = 07bh
_inv_pe = 07bh
_inv_po = 07ah
_inv_s = 079h
_inv_z = 075h
_inv_un = 0ebh ;Do not invert unconditional (jmp short)
_repcnt = 00h ;Number of last _rep
_elsecnt = 00h ;Number of last _if
_whilecnt = 00h ;Number of last _do
_rep_ptr = 00h ;Stack pointer for _rep stack
_else_ptr = 00h ;Stack pointer for _if stack
_while_ptr = 00h ;Stack pointer for _do stack
_num = 00h ;Number last popped off a stack
_defined = 00h ;Set by _?def (q.v.)
.xcref _num,_defined,_repcnt ;Do not cross reference
.xcref _elsecnt,_whilecnt
.xcref _rep_ptr,_else_ptr
.xcref _while_ptr
.xcref _inv_a,_inv_ae,_inv_b,_inv_be
.xcref _inv_c,_inv_e,_inv_g,_inv_ge
.xcref _inv_l,_inv_le,_inv_na,_inv_nae
.xcref _inv_nb,_inv_nbe,_inv_nc,_inv_ne
.xcref _inv_ng,_inv_nge,_inv_nl,_inv_nle
.xcref _inv_no,_inv_np,_inv_ns,_inv_nz
.xcref _inv_o,_inv_p,_inv_pe,_inv_po
.xcref _inv_s,_inv_z,_inv_un
.list ;Listing back on
Listing 2
...
tab equ 09h ;ASCII horizontal tab character
...
include STRUCT.ASM ;Include control structure macrosè ...
;
;---------------------
;Procedure expand_tabs
;
;Expand tabs to spaces in string (assumes tabs every eight columns).
;
;Entry:
; Pointer to string (00h terminated) in ds:si
; Pointer to destination buffer in es:di
; Direction flag clear
;Exit:
; Ax, si, di altered
;---------------------
;
expand_tabs proc near
_do
lodsb ;Get character in al
test al,al
_while ne ;While not end of string
cmp al,tab
_if e ;If tab character
mov al,' ' ;Will pad with spaces
_repeat
stosb ;Pad
test di,000000111b
_until z ;Repeat until eight character boundary
_else ;If not tab
stosb ;Save character
_endif
_endwh
stosb ;Move 00h terminator
ret
expand_tabs endp
...